package org.calrissian.restdoclet.model.type.property;

import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Type;
import org.calrissian.restdoclet.model.Model;
import org.calrissian.restdoclet.model.ModelProperty;
import org.calrissian.restdoclet.model.type.ParamTypeInfo;
import org.calrissian.restdoclet.model.type.ParamTypeInfos;

import java.util.Map;

import static org.calrissian.restdoclet.util.TypeUtils.*;

/**
 * 这时拥有实际类型但是包含了泛型的字段的处理器
 * 即该字段的类型不用解析，声明的就是一个实际的类型，但包含了泛型,如User<T>
 * Created by admin on 2017/9/3.
 */
public class ConcreteParamerterizedModelPropertyGentor extends ModelPropertyGenerator{

    @Override
    public boolean belongToThisGenerator(Type fieldType, Type ownerType) {
        if(fieldType.asParameterizedType() != null) {
            return true;
        }
        return false;
    }

    @Override
    public ModelProperty generate(Type fieldType, FieldDoc fieldDoc, Type ownerType, Map<String, Model> result, RootDoc rootDoc, ParamTypeInfos paramTypeInfos) {

        ModelProperty modelProperty = getBaseModelProperty(fieldType, fieldDoc);

        Type[] fieldTypeVariables = fieldType.asParameterizedType().typeArguments();
        ParamTypeInfo paramTypeInfo = paramTypeInfos.get(ownerType.toString());
        for(Type fieldTypeVariable: fieldTypeVariables) {
            Type caType = fieldTypeVariable;
            if(paramTypeInfo != null) {
                if(paramTypeInfo.getParamType(fieldTypeVariable.qualifiedTypeName()) != null) {
                    caType = paramTypeInfo.getParamType(fieldTypeVariable.qualifiedTypeName());
                }
            }
            if (needLoad(caType)
                    && !result.containsKey(dataType(caType))) {
                result.putAll(getModel(result, caType, rootDoc, getAllParamTypeInfos(caType, paramTypeInfos)));
            }
        }
        if (needLoad(fieldType)
                && !result.containsKey(dataType(fieldType))) {
            result.putAll(getModel(result, fieldType, rootDoc, getAllParamTypeInfos(fieldType, paramTypeInfos)));
        }

        return modelProperty;
    }
}
